/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __HARDWAREMANAGER__
#define __HARDWAREMANAGER__

#include <list>
#include <vector>
#include "HardwareDependentObject.h"

namespace liba
{

template<class Ha>
class HardwareManager
{
public:
	typedef Ha hardware_type;
	typedef HardwareDependentObjectBase<hardware_type> dependent_type;
	typedef std::list<dependent_type *> DepList;
	typedef std::list<hardware_type *> HardwareList;
	static void add_dependent( dependent_type * dep )
	{
		typename HardwareList::iterator it = hardwares->begin();
		for( ; it != hardwares->end(); ++it )
			dep->on_add_hardware( *it );

		dep_list->push_back(dep);
	}
	static void remove_dependent( dependent_type * dep )
	{
		typename HardwareList::iterator it = hardwares->begin();
		for( ; it != hardwares->end(); ++it )
			dep->on_remove_hardware( *it );

		dep_list->remove(dep);
	}
	static void add_hardware( hardware_type * ha )
	{
		hardwares->push_back( ha );
		typename DepList::iterator it = dep_list->begin();
		for( ; it != dep_list->end(); ++it )
			(*it)->on_add_hardware( ha );
	}
	static void remove_hardware( hardware_type * ha )
	{
		typename DepList::iterator it = dep_list->begin();
		for( ; it != dep_list->end(); ++it )
			(*it)->on_remove_hardware( ha );
			
		hardwares->remove( ha );
	}
	static const HardwareList & get_hardwares()
	{
		return *hardwares;
	}
	class Creator
	{
	public:
		Creator()
		{
			if( hardwares || dep_list )
				THROW(Gluck(__FUNCTION__, "hardwares already exist"));
			hardwares = new HardwareList;
			dep_list = new DepList;
		}
		~Creator()
		{
			delete hardwares; hardwares = 0;
			delete dep_list; dep_list = 0;
		}
	};
private:
	static HardwareList * hardwares;
	static DepList * dep_list;
};

template<class Ha>
typename HardwareManager<Ha>::HardwareList * HardwareManager<Ha>::hardwares = 0;

template<class Ha>
typename HardwareManager<Ha>::DepList * HardwareManager<Ha>::dep_list = 0;

template<class Ha, class Na>
class HardwareManagerNamed : public HardwareManager<Ha>
{
	typedef liba::HardwareManager<Ha> HardwareManager;
public:
	static typename HardwareManagerNamed<Ha, Na>::hardware_type * find_hardware(const Na & name)
	{
		typename HardwareManager::HardwareList::const_iterator it = HardwareManager::get_hardwares().begin();
		for( ; it != HardwareManager::get_hardwares().end(); ++it )
			if( (*it)->get_name() == name )
				return (*it);
		return 0;
	}
	static std::vector<Na> get_hardware_names()
	{
		std::vector<Na> hardware_names;
		typename HardwareManager::HardwareList::const_iterator it = HardwareManager::get_hardwares().begin();
		for( ; it != HardwareManager::get_hardwares().end(); ++it )
		{
			hardware_names.push_back( (*it)->get_name() );
		}
		return hardware_names;
	}
};

} // namespace liba
using namespace liba;

#endif // __HARDWAREMANAGER__

